#include <linux/module.h>
#include <asm/semaphore.h>
#include <linux/fs.h>
#include <linux/kernel.h>
#include <linux/moduleparam.h>
#include <linux/slab.h>
#include <linux/wait.h>

#define DEBUG
#include "debug.h"
#include "rbuffer.h"
#include "fifoops.h"

MODULE_AUTHOR("Jairo Ramos - Soledad Singh - Leandro Demarco");
MODULE_LICENSE ("GPL");
MODULE_DESCRIPTION ("Controlador para dispositivo FIFO");

static unsigned int major = 250;
static unsigned int size = 100;
static char * name = "fifo";

/** Declaramos las variables extern de fifoops.h 
  * la estructura de file_operations se define en fifoops.c */
rbuffer_t buffer;
struct semaphore sem_read;
struct semaphore sem_write;
struct semaphore sem_buffer;
wait_queue_head_t cola_read;
wait_queue_head_t cola_write;

module_param(major, uint, S_IRUGO);
module_param(size, uint, S_IRUGO);

int fifo_init(void)
{
	int err = 0;

	/** inicializamos las variables globales **/
	init_waitqueue_head(&cola_read);
	init_waitqueue_head(&cola_write);

	sema_init(&sem_read, 1);
	sema_init(&sem_write, 1);
	sema_init(&sem_buffer, 1);

	err = register_chrdev(major, name, &fifo_ops);
	if (err == 0) /* registro exitoso */
	{
		dprintk("Carga satisfactoria, con major=%d y size=%d\n",
				major, size);
		/* creamos el buffer compartido */
		buffer = rbuffer_create(size);
	}
	else /* fallo el registro */
	{
		dprintk ("%s: No se pudo registrar el dispositivo, con major = %d.\n",
					name, major);
		err = -1;
	}

	return err;
}

void fifo_exit(void)
{
	unregister_chrdev(major, name);
	rbuffer_destroy(buffer);
	dprintk("%s: Desregistro satisfactorio, con major = %d\n", name, major);
}

module_init(fifo_init);
module_exit(fifo_exit);
